package hmvictor.jpql;

import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.filesystems.FileChooserBuilder;
import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle.Messages;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;
import org.openide.util.actions.Presenter;
import org.openide.windows.WindowManager;

@ActionID(
        category = "File",
        id = "hmvictor.jpql.RecentFiles"
)
@ActionRegistration(
        displayName = "#CTL_RecentFiles", lazy = false
)
@ActionReference(path = "Menu/File", position = 1750)
@Messages("CTL_RecentFiles=Recent Files")
public class RecentFilesAction extends AbstractAction implements LookupListener, ContextAwareAction, Presenter.Menu {

    private final Lookup.Result<RecentFile> recentFiles;
    private JMenu menu;
    private List<JMenuItem> items = new LinkedList<>();

    public RecentFilesAction() {
        this(Utilities.actionsGlobalContext());
    }

    public RecentFilesAction(Lookup lkp) {
        recentFiles = lkp.lookupResult(RecentFile.class);
        recentFiles.addLookupListener(
                WeakListeners.create(LookupListener.class, this, recentFiles));
    }

    @Override
    public JMenuItem getMenuPresenter() {
        if (menu == null) {
            menu = new JMenu("Recent Files");
            try {
                JPQLEditorTopComponent editor = (JPQLEditorTopComponent) WindowManager.getDefault().findTopComponent("JQPLEditorTopComponent");
                JPQLEditorTopComponent.readRecentFiles().forEach((file) -> {
                    JMenuItem item = new JMenuItem(file.getAbsolutePath());
                    item.addActionListener((e) -> {
                        boolean cancelled = false;
                        try {
                            if (editor.isThereUnsavedContent()) {
                                NotifyDescriptor.Confirmation msg = new NotifyDescriptor.Confirmation("There are unsaved content. Do you want to save it first?", NotifyDescriptor.YES_NO_CANCEL_OPTION,
                                        NotifyDescriptor.QUESTION_MESSAGE
                                );
                                Object result = DialogDisplayer.getDefault().notify(msg);
                                if (NotifyDescriptor.YES_OPTION.equals(result)) {
                                    File f = editor.getFile();
                                    if (f == null) {
                                        File home = new File(System.getProperty("user.home"));
                                        f = new FileChooserBuilder("user-dir").setTitle("Save File").setDefaultWorkingDirectory(home).setApproveText("Save").showSaveDialog();
                                    }
                                    if (f != null) {
                                        editor.saveContent(file);
                                    } else {
                                        cancelled = true;
                                    }
                                } else if (NotifyDescriptor.CANCEL_OPTION.equals(result)) {
                                    cancelled = true;
                                }
                            }
                            if (!cancelled) {
                                editor.loadContent(file);
                            }
                        } catch (IOException ex) {
                            Exceptions.printStackTrace(ex);
                        }
                    });
                    menu.add(item);
                    items.add(item);
                });
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        return menu;
    }

    @Override
    public void resultChanged(LookupEvent le) {
        recentFiles.allInstances().stream().forEach((recentFile) -> {
            boolean found = false;
            for (JMenuItem menuItem : items) {
                if (menuItem.getText().equals(recentFile.getFile().getName())) {
                    found = true;
                }
            }
            if (!found) {
                menu.add(recentFile.getFile().getAbsolutePath());
            }
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // not used
    }

    @Override
    public Action createContextAwareInstance(Lookup lkp) {
        return new RecentFilesAction(lkp);
    }

}
